home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / vm / vmMap.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  18KB  |  679 lines

  1. /* vmMap.c -
  2.  *
  3.  *         This file contains routines to map pages into the kernel's address
  4.  *    space.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/kernel/vm/RCS/vmMap.c,v 9.11 91/04/19 21:47:16 kupfer Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14. #include <sprite.h>
  15. #include <vm.h>
  16. #include <vmInt.h>
  17. #include <lock.h>
  18. #include <list.h>
  19. #include <proc.h>
  20. #include <sched.h>
  21. #include <sync.h>
  22. #include <sys.h>
  23. #include <vmHack.h>
  24. #ifdef VM_CHECK_BSTRING_ACCESS
  25. #include <dbg.h>
  26. #include <stdlib.h>
  27. #endif
  28.  
  29.  
  30. Sync_Condition    mappingCondition;
  31.  
  32. int    vmNumMappedPages = 16;
  33. int    vmMapBasePage;
  34. int    vmMapEndPage;
  35. Address vmMapBaseAddr;
  36. Address vmMapEndAddr;
  37.  
  38.  
  39. #ifdef VM_CHECK_BSTRING_ACCESS
  40. /* 
  41.  * Temporary: keep a list of which processes have called
  42.  * Vm_MakeAccessible.  bcopy et al will check the list to verify that
  43.  * it's okay to access the user address space.
  44.  */
  45.  
  46. typedef struct {
  47.     List_Links        links;
  48.     Proc_ControlBlock    *procPtr;
  49.     Address        startAddr; /* user address */
  50.     int            numBytes; /* as returned by Vm_MakeAccessible */
  51.     int            refCount;
  52. } VmAccessInfo;
  53.  
  54. List_Links    vmAccessListHdr;
  55. List_Links    *vmAccessList = &vmAccessListHdr;
  56. static Sync_Lock    vmAccessListLock;
  57.  
  58. Boolean        vmDoAccessChecks = FALSE;
  59.  
  60. /* Forward references: */
  61.  
  62. static void RegisterAccess _ARGS_ ((Proc_ControlBlock *procPtr,
  63.                     Address startAddr, int numBytes));
  64. static void RemoveAccess _ARGS_ ((Proc_ControlBlock *procPtr,
  65.                   Address startAddr, int numBytes));
  66. static VmAccessInfo *
  67. FindAccessElement _ARGS_ ((Proc_ControlBlock *procPtr, Address startAddr,
  68.                int numBytes));
  69.  
  70. #endif /* VM_CHECK_BSTRING_ACCESS */
  71.  
  72.  
  73. /*
  74.  * ----------------------------------------------------------------------------
  75.  *
  76.  * VmMapPage --
  77.  *
  78.  *      Map the given physical page into the kernels virtual address space.  
  79.  *    The kernel virtual address where the page is mapped is returned.
  80.  *    This routine is used when a page frame that is in a user's address
  81.  *    space needs to be accessed by the kernel.
  82.  *
  83.  * Results:
  84.  *      The kernel virtual address where the page is mapped.
  85.  *
  86.  * Side effects:
  87.  *      Kernel page table modified to validate the mapped page.
  88.  *
  89.  * ----------------------------------------------------------------------------
  90.  */
  91. ENTRY Address
  92. VmMapPage(pfNum)
  93.     unsigned int    pfNum;    /* The page frame number that to map. */
  94. {
  95.     register Vm_PTE    *ptePtr;
  96.     Vm_VirtAddr        virtAddr;
  97.     register int    virtPage;
  98.     register Vm_Segment    *segPtr;
  99.  
  100.     LOCK_MONITOR;
  101.  
  102.     segPtr = vm_SysSegPtr;
  103.     /*
  104.      * Search through the page table until a non-resident page is found or we
  105.      * go past the pte that can be used for mapping.  If none can be found 
  106.      * then sleep.
  107.      */
  108.     while (TRUE) {
  109.     for (virtPage = vmMapBasePage,
  110.          ptePtr = VmGetPTEPtr(segPtr, vmMapBasePage);
  111.          virtPage < vmMapEndPage;
  112.          virtPage++, VmIncPTEPtr(ptePtr, 1)) {
  113.         if (!(*ptePtr & VM_PHYS_RES_BIT)) {
  114.         virtAddr.segPtr = segPtr;
  115.         virtAddr.page = virtPage;
  116.         virtAddr.offset = 0;
  117.         virtAddr.flags = 0;
  118.         virtAddr.sharedPtr = (Vm_SegProcList *)NIL;
  119.         *ptePtr |= VM_PHYS_RES_BIT | pfNum;
  120.         VmMach_PageValidate(&virtAddr, *ptePtr);
  121. #ifdef spur
  122.         /*
  123.          * Until we figure out how to handle virtual synonyms on 
  124.          * SPUR, we always make map address noncachable. 
  125.          */
  126.         VmMach_MakeNonCachable(&virtAddr, *ptePtr);
  127. #endif
  128.         UNLOCK_MONITOR;
  129.         return((Address) (virtPage << vmPageShift));
  130.         }
  131.     }
  132.     vmStat.mapPageWait++;
  133.     (void) Sync_Wait(&mappingCondition, FALSE);
  134.     }
  135. }
  136.  
  137.  
  138. /*
  139.  * ----------------------------------------------------------------------------
  140.  *
  141.  * VmRemapPage --
  142.  *
  143.  *      Map the given physical page into the kernels virtual address space
  144.  *    at the given virtual address.  The address given must be produced from
  145.  *    VmMapPage.  The purpose of this routine is to reduce overhead for
  146.  *    routines that have to map numerous page frames into the kernel's
  147.  *    virtual address space.
  148.  *
  149.  * Results:
  150.  *      None.
  151.  *
  152.  * Side effects:
  153.  *      Kernel page table modified.
  154.  *
  155.  * ----------------------------------------------------------------------------
  156.  */
  157. ENTRY void
  158. VmRemapPage(addr, pfNum)
  159.     Address        addr;    /* Virtual address to map the page frame at. */
  160.     unsigned int    pfNum;    /* The page frame number to map. */
  161. {
  162.     register    Vm_PTE    *ptePtr;
  163.     Vm_VirtAddr        virtAddr;
  164.     register Vm_Segment    *segPtr;
  165.  
  166.    
  167.     LOCK_MONITOR;
  168.  
  169.     segPtr = vm_SysSegPtr;
  170.     virtAddr.segPtr = segPtr;
  171.     virtAddr.page = (unsigned int) (addr) >> vmPageShift;
  172.     virtAddr.sharedPtr = (Vm_SegProcList *) NIL;
  173.     /*
  174.      * Clean the old page from the cache.
  175.      */
  176.     VmMach_FlushPage(&virtAddr, TRUE);
  177.     ptePtr = VmGetPTEPtr(segPtr, virtAddr.page);
  178.     *ptePtr &= ~VM_PAGE_FRAME_FIELD;
  179.     *ptePtr |= pfNum;
  180.     VmMach_PageValidate(&virtAddr, *ptePtr);
  181. #ifdef spur
  182.     /*
  183.      * Until we figure out how to handle virtual synonyms on 
  184.      * SPUR, we always make map address noncachable. 
  185.      */
  186.     VmMach_MakeNonCachable(&virtAddr, *ptePtr);
  187. #endif
  188.  
  189.     UNLOCK_MONITOR;
  190. }
  191.  
  192.  
  193. /*
  194.  * ----------------------------------------------------------------------------
  195.  *
  196.  * VmUnmapPage --
  197.  *
  198.  *      Free up a page which has been mapped by VmMapPage.
  199.  *
  200.  * Results:
  201.  *      None.
  202.  *
  203.  * Side effects:
  204.  *      Kernel page table modified to invalidate the page.
  205.  *
  206.  * ----------------------------------------------------------------------------
  207.  */
  208. ENTRY void
  209. VmUnmapPage(mappedAddr)
  210.     Address    mappedAddr;    /* Virtual address of the page that is being
  211.                    unmapped. */
  212. {
  213.     Vm_VirtAddr        virtAddr;
  214.     Vm_PTE        *ptePtr;
  215.  
  216.     LOCK_MONITOR;
  217.  
  218.     virtAddr.segPtr = vm_SysSegPtr;
  219.     virtAddr.page = (unsigned int) (mappedAddr) >> vmPageShift;
  220.     virtAddr.offset = 0;
  221.     virtAddr.flags = 0;
  222.     virtAddr.sharedPtr = (Vm_SegProcList *)NIL;
  223.  
  224.     ptePtr = VmGetPTEPtr(vm_SysSegPtr, virtAddr.page);
  225.     *ptePtr &= ~(VM_PHYS_RES_BIT | VM_PAGE_FRAME_FIELD);
  226.     VmMach_PageInvalidate(&virtAddr, Vm_GetPageFrame(*ptePtr), FALSE);
  227.  
  228.     Sync_Broadcast(&mappingCondition);
  229.  
  230.     UNLOCK_MONITOR;
  231. }
  232.  
  233.  
  234. /*
  235.  * ----------------------------------------------------------------------------
  236.  *
  237.  * Vm_MakeAccessible --
  238.  *
  239.  *      Make sure that the given range of address are valid.
  240.  *
  241.  * Results:
  242.  *    Return the address passed in in *retAddrPtr and the number of bytes
  243.  *    that are actually valid in *retBytesPtr.
  244.  *
  245.  * Side effects:
  246.  *      If the address that is being made accessible falls into a heap or
  247.  *    stack segment then the heap segment for the currently executing
  248.  *    process has the page table in-use count incremented.  This is to
  249.  *    ensure that the addresses remain valid until Vm_MakeUnaccessible
  250.  *    is called.
  251.  *    (Historical note: this function was originally used to access 
  252.  *    pages without worrying about page faults.  This scheme proved 
  253.  *    too slow, so there was a switch to CopyIn/CopyOut.  Now this 
  254.  *    function is useful to ensure the validity of pte pointers.  
  255.  *    See the sychronization comments in vmInt.h)
  256.  *
  257.  * ----------------------------------------------------------------------------
  258.  */
  259. /*ARGSUSED*/
  260. void
  261. Vm_MakeAccessible(accessType, numBytes, startAddr, retBytesPtr, retAddrPtr)
  262.     int            accessType;    /* One of VM_READONLY_ACCESS, 
  263.                      * VM_OVERWRITE_ACCESS, 
  264.                      * VM_READWRITE_ACCESS. */
  265.     int            numBytes;    /* The maximum number of bytes to make 
  266.                      * accessible. */
  267.     Address        startAddr;    /* The address in the user's address
  268.                      * space to start at. */
  269.     register    int    *retBytesPtr;    /* The actual number of bytes 
  270.                      * made accessible. */
  271.     register    Address    *retAddrPtr;    /* The kernel virtual address that
  272.                      * can be used to access the bytes. */
  273. {
  274.     register    Vm_Segment    *segPtr;
  275.     register    Vm_PTE        *ptePtr;
  276.     Vm_VirtAddr            virtAddr;
  277.     int                firstPage;
  278.     int                lastPage;
  279.     Proc_ControlBlock        *procPtr;
  280.  
  281.     procPtr = Proc_GetCurrentProc();
  282.  
  283.     /*
  284.      * Parse the virtual address to determine which segment that this page
  285.      * falls into and which page in the segment.
  286.      */
  287.     VmVirtAddrParse(procPtr, startAddr, &virtAddr);
  288.  
  289.     segPtr = virtAddr.segPtr;
  290.     /*
  291.      * See if the beginning address falls into a segment.
  292.      */
  293.     if (segPtr == (Vm_Segment *) NIL) {
  294.     *retBytesPtr = 0;
  295.     *retAddrPtr = (Address) NIL;
  296.     goto done;
  297.     }
  298.  
  299.     procPtr->vmPtr->numMakeAcc++;
  300.     *retBytesPtr = numBytes;
  301.  
  302. #ifdef    sequent
  303.     /*
  304.      * Relocate the returned address to allow kernel to address it
  305.      * directly.  mach_KernelVirtAddrUser should be defined for all
  306.      * machines (with value == 0 on most).
  307.      */
  308.     *retAddrPtr = startAddr + mach_KernelVirtAddrUser;
  309. #else
  310.     *retAddrPtr = startAddr;
  311. #endif  /* sequent */
  312.  
  313.     firstPage = virtAddr.page;
  314.     lastPage = ((unsigned int) (startAddr) + numBytes - 1) >> vmPageShift;
  315.     if (segPtr->type == VM_STACK) {
  316.     /*
  317.      * If ending address goes past the end of the
  318.      * stack then truncate it.  
  319.      */
  320.     if (lastPage > mach_LastUserStackPage) {
  321.         *retBytesPtr = (int)mach_MaxUserStackAddr - (int)startAddr;
  322.     }
  323.     /* 
  324.      * Since is the stack segment we know the whole range
  325.      * of addresses is valid so just return.
  326.      */
  327.     goto done;
  328.     }
  329.  
  330.     /*
  331.      * Truncate range of addresses so that it falls into the code or heap
  332.      * heap segment.
  333.      */
  334.     if (lastPage - segPtr->offset + 1 > segPtr->numPages) {
  335.     lastPage = segPtr->offset + segPtr->numPages - 1;
  336.     *retBytesPtr = ((lastPage + 1) << vmPageShift) - (int) startAddr;
  337.     }
  338.     if (segPtr->type == VM_CODE) {
  339.     /* 
  340.      * Code segments are mapped contiguously so we know the whole range
  341.      * of pages is valid.
  342.      */
  343.     goto done;
  344.     }
  345.     /*
  346.      * We are left with a heap segment.  Go through the page table and make
  347.      * sure all of the pages in the range are valid.  Stop as soon as hit an
  348.      * invalid page.  We can look at the page table without fear because the
  349.      * segment has been prevented from being expanded by VmVirtAddrParse.
  350.      */
  351.     for (ptePtr = &(segPtr->ptPtr[virtAddr.page - segPtr->offset]);
  352.          virtAddr.page <= lastPage; 
  353.      virtAddr.page++, ptePtr++) {
  354.     if (!(*ptePtr & VM_VIRT_RES_BIT)) {
  355.         break;
  356.     }
  357.     }
  358.     /*
  359.      * If we couldn't map anything then just return.
  360.      */
  361.     if (virtAddr.page == firstPage) {
  362.         VmDecPTUserCount(procPtr->vmPtr->segPtrArray[VM_HEAP]);
  363.     procPtr->vmPtr->numMakeAcc--;
  364.     *retBytesPtr = 0;
  365.     *retAddrPtr = (Address) NIL;
  366.     goto done;
  367.     }
  368.     /* 
  369.      * If we couldn't make all of the requested pages accessible then return 
  370.      * the number of bytes that we actually made accessible.
  371.      */
  372.     if (virtAddr.page <= lastPage) {
  373.     *retBytesPtr = (virtAddr.page << vmPageShift) - (int) startAddr;
  374.     }
  375.  
  376.  done:
  377. #ifdef VM_CHECK_BSTRING_ACCESS
  378.     if (vmDoAccessChecks && !dbg_BeingDebugged && *retBytesPtr != 0) {
  379.     RegisterAccess(procPtr, startAddr, *retBytesPtr);
  380.     }
  381. #else 
  382.     ;
  383. #endif
  384. }
  385.  
  386.  
  387. /*
  388.  ----------------------------------------------------------------------
  389.  *
  390.  * Vm_MakeUnaccessible
  391.  *
  392.  *    Take the given kernel virtual address and make the range of pages
  393.  *    that it addresses unaccessible.  All that has to be done is to
  394.  *    decrement the in-use count on the page table for the calling process's
  395.  *    heap segment.
  396.  *
  397.  * Results:
  398.  *    None.
  399.  *
  400.  * Side effects:
  401.  *    Heap segment page table in use count decremented if the address 
  402.  *    falls into a heap or stack segment.
  403.  *
  404.  *----------------------------------------------------------------------
  405.  */
  406. /*ARGSUSED*/
  407. ENTRY void
  408. Vm_MakeUnaccessible(addr, numBytes)
  409.     Address        addr;
  410.     int            numBytes;
  411. {
  412.     Proc_ControlBlock      *procPtr;
  413.     register Vm_Segment    *segPtr;
  414.  
  415. #ifdef    sequent
  416.     /*
  417.      * Un-relocate the address back to user-relative.
  418.      */
  419.     addr -= mach_KernelVirtAddrUser;
  420. #endif    /* sequent */
  421.  
  422.     LOCK_MONITOR;
  423.  
  424.     procPtr = Proc_GetCurrentProc();
  425.     segPtr = procPtr->vmPtr->segPtrArray[VM_HEAP];
  426.     procPtr->vmPtr->numMakeAcc--;
  427.  
  428.     if (((unsigned int) (addr) >> vmPageShift) >= segPtr->offset) {
  429.     /*
  430.      * This address falls into a stack or heap segment.  The heap segment
  431.      * was prevented from being expanded by Vm_MakeAccessible so we have
  432.      * to let it be expanded now.
  433.      */
  434.         segPtr->ptUserCount--;
  435.         if (segPtr->ptUserCount < 0) {
  436.             panic("Vm_MakeUnaccessible: expand count < 0\n");
  437.         }
  438.         if (segPtr->ptUserCount == 0) {
  439.             Sync_Broadcast(&segPtr->condition);
  440.         }
  441.     }
  442.  
  443.     UNLOCK_MONITOR;
  444.  
  445. #ifdef VM_CHECK_BSTRING_ACCESS
  446.     if (vmDoAccessChecks && !dbg_BeingDebugged && numBytes != 0) {
  447.     RemoveAccess(procPtr, addr, numBytes);
  448.     }
  449. #endif
  450. }
  451.  
  452. #ifdef VM_CHECK_BSTRING_ACCESS
  453.  
  454. /*
  455.  *----------------------------------------------------------------------
  456.  *
  457.  * RegisterAccess --
  458.  *
  459.  *    Record the fact that the given process has acquired access to 
  460.  *    the given range of addresses.
  461.  *
  462.  * Results:
  463.  *    None.
  464.  *
  465.  * Side effects:
  466.  *    Adds an element to the access linked list if the range isn't 
  467.  *    already registered.  Bumps the reference count for the range 
  468.  *    if it has.
  469.  *
  470.  *----------------------------------------------------------------------
  471.  */
  472.  
  473. static void
  474. RegisterAccess(procPtr, startAddr, numBytes)
  475.     Proc_ControlBlock    *procPtr;
  476.     Address        startAddr; /* user address */
  477.     int            numBytes; /* as returned by Vm_MakeAccessible */
  478. {
  479.     VmAccessInfo *accessPtr;
  480.  
  481.     Sync_GetLock(&vmAccessListLock);
  482.  
  483.     accessPtr = FindAccessElement(procPtr, startAddr, numBytes);
  484.     if (accessPtr != (VmAccessInfo *)NIL) {
  485.     accessPtr->refCount++;
  486.     } else {
  487.     accessPtr = (VmAccessInfo *)malloc(sizeof(VmAccessInfo));
  488.     accessPtr->procPtr = procPtr;
  489.     accessPtr->startAddr = startAddr;
  490.     accessPtr->numBytes = numBytes;
  491.     accessPtr->refCount = 1;
  492.     List_InitElement((List_Links *)accessPtr);
  493.     List_Insert((List_Links *)accessPtr,
  494.             LIST_ATREAR(vmAccessList));
  495.     }
  496.  
  497.     Sync_Unlock(&vmAccessListLock);
  498. }
  499.  
  500.  
  501. /*
  502.  *----------------------------------------------------------------------
  503.  *
  504.  * RemoveAccess --
  505.  *
  506.  *    Forget that the given process has access to the given range of 
  507.  *    addresses.
  508.  *
  509.  * Results:
  510.  *    None.
  511.  *
  512.  * Side effects:
  513.  *    Decrements the reference count for the given range.  Removes 
  514.  *    the range from the list if the count goes to 0.  We assume
  515.  *    that the caller will surrender access to the entire range that
  516.  *    was acquired, rather than surrendering only part of the range.
  517.  *
  518.  *----------------------------------------------------------------------
  519.  */
  520.  
  521. static void
  522. RemoveAccess(procPtr, startAddr, numBytes)
  523.     Proc_ControlBlock    *procPtr;
  524.     Address        startAddr; /* user address */
  525.     int            numBytes; /* as returned by Vm_MakeAccessible */
  526. {
  527.     VmAccessInfo *accessPtr;
  528.  
  529.     Sync_GetLock(&vmAccessListLock);
  530.  
  531.     accessPtr = FindAccessElement(procPtr, startAddr, numBytes);
  532.     if (accessPtr == (VmAccessInfo *)NIL) {
  533.     vmDoAccessChecks = FALSE;
  534.     panic("Vm_MakeUnAccessible: address range not registered");
  535.     }
  536.  
  537.     accessPtr->refCount--;
  538.     if (accessPtr->refCount <= 0) {
  539.     List_Remove((List_Links *)accessPtr);
  540.     free((char *)accessPtr);
  541.     }
  542.  
  543.     Sync_Unlock(&vmAccessListLock);
  544. }
  545.  
  546.  
  547. /*
  548.  *----------------------------------------------------------------------
  549.  *
  550.  * FindAccessElement --
  551.  *
  552.  *    Find the element in the access list corresponding to the given 
  553.  *    arguments.  The caller should be holding the lock for the 
  554.  *    access list.
  555.  *
  556.  * Results:
  557.  *    Returns a pointer to the element if found, NIL if not found.
  558.  *
  559.  * Side effects:
  560.  *    None.
  561.  *
  562.  *----------------------------------------------------------------------
  563.  */
  564.  
  565. static VmAccessInfo *
  566. FindAccessElement(procPtr, startAddr, numBytes)
  567.     Proc_ControlBlock *procPtr;
  568.     Address    startAddr;
  569.     int        numBytes;
  570. {
  571.     VmAccessInfo *accessPtr;
  572.  
  573.     LIST_FORALL(vmAccessList, (List_Links *)accessPtr) {
  574.     if (accessPtr->procPtr == procPtr
  575.         && accessPtr->startAddr == startAddr
  576.         && accessPtr->numBytes == numBytes) {
  577.         return accessPtr;
  578.     }
  579.     }
  580.  
  581.     return (VmAccessInfo *)NIL;
  582. }
  583.  
  584.  
  585. /*
  586.  *----------------------------------------------------------------------
  587.  *
  588.  * Vm_IsAccessible --
  589.  *
  590.  *    Verify that Vm_MakeAccessible has been called for the given 
  591.  *    range of addresses.
  592.  *
  593.  * Results:
  594.  *    Returns if okay, panics if not.
  595.  *
  596.  * Side effects:
  597.  *    None.
  598.  *
  599.  *----------------------------------------------------------------------
  600.  */
  601.  
  602. void
  603. Vm_CheckAccessible(startAddr, numBytes)
  604.     Address    startAddr;
  605.     int        numBytes;
  606. {
  607.     VmAccessInfo *accessPtr;
  608.     Proc_ControlBlock    *procPtr;
  609.     Boolean okay = FALSE;
  610.  
  611.     if (!vmDoAccessChecks || dbg_BeingDebugged) {
  612.     return;
  613.     }
  614.  
  615.     /* 
  616.      * All accesses to kernel memory are okay.  Assume that the 
  617.      * requested region doesn't wrap around the end of memory.
  618.      */
  619.     if (startAddr > mach_LastUserAddr
  620.         || startAddr + numBytes <= mach_FirstUserAddr) {
  621.     return;
  622.     }
  623.  
  624.     procPtr = Proc_GetCurrentProc();
  625.  
  626.     Sync_GetLock(&vmAccessListLock);
  627.  
  628.     LIST_FORALL(vmAccessList, (List_Links *)accessPtr) {
  629.     if (accessPtr->procPtr != procPtr) {
  630.         continue;
  631.     }
  632.     /* 
  633.      * Check the start and end of the given range against the 
  634.      * range in the list element.  If the given range can't fit in 
  635.      * the list element, go on to the next element.
  636.      */
  637.     if (accessPtr->startAddr <= startAddr
  638.         && (accessPtr->startAddr + accessPtr->numBytes
  639.             >= startAddr + numBytes)) {
  640.         okay = TRUE;
  641.         break;
  642.     }
  643.     }
  644.  
  645.     Sync_Unlock(&vmAccessListLock);
  646.  
  647.     if (!okay) {
  648.     vmDoAccessChecks = FALSE;
  649.     panic("Vm_IsAccessible: accessing user memory improperly");
  650.     }
  651. }
  652.  
  653.  
  654.  
  655. /*
  656.  *----------------------------------------------------------------------
  657.  *
  658.  * VmMapInit --
  659.  *
  660.  *    Initialize the access list, lock, etc.
  661.  *
  662.  * Results:
  663.  *    None.
  664.  *
  665.  * Side effects:
  666.  *    The access list and lock are initialized.
  667.  *
  668.  *----------------------------------------------------------------------
  669.  */
  670.  
  671. void
  672. VmMapInit()
  673. {
  674.     Sync_LockInitDynamic(&vmAccessListLock, "Vm:accessListLock");
  675.     List_Init(vmAccessList);
  676. }
  677.  
  678. #endif /* VM_CHECK_BSTRING_ACCESS */
  679.